package han.chensing.latos.maker.res;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;

import java.nio.charset.StandardCharsets;

public abstract class LoadEntry {
    public enum Type{
        Texture,TextureRegion,Sound,TTFGenerator,TTF,Skin,ShadeProgram,SmoothFont,
        FileHandle
    }
    public Type type;
    public String name;

    public abstract Object realLoad(Res res);

    public LoadEntry(Type type, String name){
        this.type=type;
        this.name=name;
    }

    public static class TextureEntry extends LoadEntry {
        private final String path;
        public TextureEntry(String name,String path) {
            super(Type.Texture,name);
            this.path=path;
        }
        @Override
        public Object realLoad(Res res) {
            return new Texture(path);
        }
    }

    public static class TextureRegionEntry extends LoadEntry {
        private final String textureName;
        public TextureRegionEntry(String name,String textureName) {
            super(Type.TextureRegion, name);
            this.textureName=textureName;
        }
        @Override
        public Object realLoad(Res res) {
            return new TextureRegion(res.get(textureName, Texture.class));
        }
    }

    public static class SoundRegionEntry extends LoadEntry{
        private final String path;
        public SoundRegionEntry(String name,String path){
            super(Type.Sound,name);
            this.path=path;
        }
        @Override
        public Object realLoad(Res res) {
            return Gdx.audio.newSound(Gdx.files.internal(path));
        }
    }

    public static class TTFGeneratorEntry extends LoadEntry{
        private final String path;
        public TTFGeneratorEntry(String name, String path) {
            super(Type.TTFGenerator, name);
            this.path = path;
        }
        @Override
        public Object realLoad(Res res) {
            return new FreeTypeFontGenerator(Gdx.files.internal(path));
        }
    }

    public static class TTFEntry extends LoadEntry{
        private final String generatorName;
        private final int size;
        public TTFEntry(String name, String generatorName, int size) {
            super(Type.TTF, name);
            this.generatorName=generatorName;
            this.size = size;
        }
        @Override
        public Object realLoad(Res res) {
            FileHandle allCharacters = res.get("allCharacters", FileHandle.class);
            FreeTypeFontGenerator.FreeTypeFontParameter freeTypeFontParameter=new FreeTypeFontGenerator.FreeTypeFontParameter();
            String fullText = new String(allCharacters.readBytes(), StandardCharsets.UTF_16BE);
            fullText=fullText.replace("\r\n","");
            String defaultChars = FreeTypeFontGenerator.DEFAULT_CHARS+fullText;
            freeTypeFontParameter.characters=defaultChars;
            freeTypeFontParameter.color= Color.WHITE;
            freeTypeFontParameter.genMipMaps=true;
            freeTypeFontParameter.minFilter= Texture.TextureFilter.MipMapLinearLinear;
            freeTypeFontParameter.magFilter= Texture.TextureFilter.Linear;
            freeTypeFontParameter.size=size;
            FreeTypeFontGenerator freeTypeFontGenerator = res.get(generatorName, FreeTypeFontGenerator.class);
            BitmapFont bitmapFont = freeTypeFontGenerator.generateFont(freeTypeFontParameter);
            return bitmapFont;
        }
    }

    public static class SkinEntry extends LoadEntry{
        private final String path;
        public SkinEntry(String name,String path) {
            super(Type.Skin, name);
            this.path=path;
        }
        @Override
        public Object realLoad(Res res) {
            res.load(name+"Json", Gdx.files.internal(path));
            Skin skin = new Skin(res.get(name + "Json", FileHandle.class));
            res.load(name, skin);
            return skin;
        }
    }

    public static class ShadeProgramEntry extends LoadEntry{
        private final String vertPath;
        private final String fragPath;
        public ShadeProgramEntry(String name, String vertPath, String fragPath) {
            super(Type.ShadeProgram,name);
            this.vertPath = vertPath;
            this.fragPath = fragPath;
        }
        @Override
        public Object realLoad(Res res) {
            ShaderProgram shaderProgram = new ShaderProgram(Gdx.files.internal(vertPath), Gdx.files.internal(fragPath));
            return shaderProgram.isCompiled()?shaderProgram:null;
        }
    }

    public static class FileHandleEntry extends LoadEntry{
        private final String path;
        public FileHandleEntry(String name, String path) {
            super(Type.FileHandle, name);
            this.path = path;
        }
        @Override
        public Object realLoad(Res res) {
            return Gdx.files.internal(path);
        }
    }
}
